﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Imaging;
using System.Reflection;
using System.Windows.Forms;
using HML.Design;

namespace HML
{
    /// <summary>
    /// 动态图片显示控件
    /// </summary>
    [Description("动态图片显示控件")]
    [DefaultProperty("Image")]
    [DefaultEvent("ImageChanged")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [Designer(typeof(GifBoxDesigner))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(GifBox), "Controls.GifBox.Resources.GifBox.bmp")]
    public class GifBox : DpiControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(GifBox)).GetName().Name, typeof(GifBox).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled= SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region 新增事件

        private static readonly object EventImageChanged = new object();
        /// <summary>
        /// 图片更改事件
        /// </summary>
        [Description("图片更改事件")]
        public event EventHandler ImageChanged
        {
            add { Events.AddHandler(EventImageChanged, value); }
            remove { Events.RemoveHandler(EventImageChanged, value); }
        }

        public delegate void FrameIndexChangedEventHandler(object sender, GifBoxFrameIndexChangedEventArgs e);
        private static readonly object EventFrameIndexChanged = new object();
        /// <summary>
        /// 活动帧的索引更改事件
        /// </summary>
        [Description("活动帧的索引更改事件")]
        public event FrameIndexChangedEventHandler FrameIndexChanged
        {
            add { Events.AddHandler(EventFrameIndexChanged, value); }
            remove { Events.RemoveHandler(EventFrameIndexChanged, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler PaddingChanged
        {
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabIndexChanged
        {
            add { base.TabIndexChanged += value; }
            remove { base.TabIndexChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabStopChanged
        {
            add { base.TabStopChanged += value; }
            remove { base.TabStopChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged
        {
            add { base.TextChanged += value; }
            remove { base.TextChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler FontChanged
        {
            add { base.FontChanged += value; }
            remove { base.FontChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler RightToLeftChanged
        {
            add { base.RightToLeftChanged += value; }
            remove { base.RightToLeftChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click
        {
            add { base.Click += value; }
            remove { base.Click -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick
        {
            add { base.MouseClick += value; }
            remove { base.MouseClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }

        #endregion

        #region 新增属性

        private bool borderVisible = false;
        /// <summary>
        ///是否显示边框
        /// </summary>
        [Description("是否显示边框")]
        [PropertyOrder(-198)]
        [DefaultValue(false)]
        public bool BorderVisible
        {
            get { return this.borderVisible; }
            set
            {
                if (this.borderVisible == value)
                    return;

                this.borderVisible = value;
                this.Invalidate();
            }
        }

        private bool isAnimation;
        /// <summary>   
        /// 是否为动态图片   
        /// </summary>  
        [Description("是否为动态图片")]
        [PropertyOrder(-196)]
        [Browsable(false)]
        [DefaultValue(false)]
        public bool IsAnimation
        {
            get { return this.isAnimation; }
        }

        private Image image = null;
        /// <summary>   
        /// 要显示的图片   
        /// </summary>
        [Description("要显示的图片")]
        [PropertyOrder(-194)]
        [Browsable(true)]
        [DefaultValue(null)]
        public Image Image
        {
            get { return this.image; }
            set
            {
                if (this.image == value)
                    return;

                if (value == null)//清除图片
                {
                    if (this.isAnimation)
                    {
                        this.StopAnimation();
                    }
                    this.image = value;
                    this.Invalidate();

                    if (!this.DesignMode)
                    {
                        this.OnImageChanged(EventArgs.Empty);
                    }
                }
                else//加载图片
                {
                    if (this.isAnimation)
                    {
                        this.StopAnimation();
                    }
                    this.image = value;

                    lock (this.image)
                    {
                        this.isAnimation = ImageAnimator.CanAnimate(this.image);
                        if (this.isAnimation)//gif图片
                        {
                            Guid[] guid = this.image.FrameDimensionsList;
                            this.frameDimension = new FrameDimension(guid[0]);
                            this.frameCount = this.image.GetFrameCount(this.frameDimension);
                            this.currentFrame = 0;
                            this.image.SelectActiveFrame(this.frameDimension, this.currentFrame);
                            this.Invalidate();

                            if (!this.DesignMode)
                            {
                                this.OnImageChanged(EventArgs.Empty);
                            }
                            if (!this.DesignMode && this.Enabled && this.Visible)
                            {
                                this.StartAnimation();
                            }
                        }
                        else//普通图片
                        {
                            this.ResetImagetFrameInfo();
                            this.Invalidate();

                            if (!this.DesignMode)
                            {
                                this.OnImageChanged(EventArgs.Empty);
                            }
                        }
                    }
                }
            }
        }

        private int frameCount = 0;
        /// <summary>   
        /// 图片总帧数  
        /// </summary>  
        [Description("图片总帧数")]
        [PropertyOrder(-192)]
        [Browsable(false)]
        public int FrameCount
        {
            get { return this.frameCount; }
        }

        private int currentFrame = -1;
        /// <summary>   
        /// 当前播放的帧索引   
        /// </summary>   
        [Description("当前播放的帧数")]
        [PropertyOrder(-190)]
        [Browsable(false)]
        public int CurrentFrame
        {
            get { return this.currentFrame; }
        }

        #endregion

        #region 重写属性

        protected override Size DefaultSize
        {
            get { return new Size(80, 80); }
        }

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new int TabIndex
        {
            get { return base.TabIndex; }
            set { base.TabIndex = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool TabStop
        {
            get { return base.TabStop; }
            set { base.TabStop = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Font Font
        {
            get { return base.Font; }
            set { base.Font = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color BackColor
        {
            get { return this.StyleAppearance.BackColor; }
            set { }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return this.StyleAppearance.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 图像的框架维度的属性
        /// </summary>
        private FrameDimension frameDimension;

        /// <summary>
        /// 是否已开启动画播放
        /// </summary>
        private bool isruning = false;

        #endregion

        public GifBox()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.StandardClick, false);
            SetStyle(ControlStyles.StandardDoubleClick, false);
            SetStyle(ControlStyles.Selectable, false);

            this.TabStop = false;
            this.OnSkinChanged();
        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;

            //图片
            if (this.Image != null)
            {
                lock (this.Image)
                {
                    Image image_tmp = null;
                    if (this.DesignMode)
                    {
                        if (this.IsAnimation)
                        {
                            this.image.SelectActiveFrame(this.frameDimension, 0);
                        }
                        image_tmp = this.Image;
                    }
                    else
                    {
                        image_tmp = this.Image;
                    }
                    g.DrawImage(image_tmp, new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height), new Rectangle(0, 0, this.Image.Width, this.Image.Height), GraphicsUnit.Pixel);
                }
            }

            // 边框
            if (this.BorderVisible)
            {
                Pen border_pen = new Pen(this.StyleAppearance.BorderColor);
                g.DrawRectangle(border_pen, this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);
                border_pen.Dispose();
            }

        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);

            if (!this.DesignMode && this.Image != null)
            {
                if (this.Enabled && this.Visible && this.FindForm() != null)
                {
                    if (!this.isruning)
                    {
                        this.StartAnimation();
                    }
                }
                else
                {
                    if (this.isruning)
                    {
                        this.StopAnimation();
                    }
                }
            }
            this.Invalidate();
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);

            if (!this.DesignMode && this.Image != null)
            {
                if (this.Enabled && this.Visible && this.FindForm() != null)
                {
                    if (!this.isruning)
                    {
                        this.StartAnimation();
                    }
                }
                else
                {
                    if (this.isruning)
                    {
                        this.StopAnimation();
                    }
                }
            }

        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);

            if (!this.DesignMode && this.Image != null)
            {
                if (this.Enabled && this.Visible && this.FindForm() != null)
                {
                    if (!this.isruning)
                    {
                        this.StartAnimation();
                    }
                }
                else
                {
                    if (this.isruning)
                    {
                        this.StopAnimation();
                    }
                }
            }

        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.Image != null && this.isruning)
                {
                    this.StopAnimation();
                    this.Image = null;
                }
            }
            base.Dispose(disposing);
        }

        #endregion

        #region 虚方法

        protected virtual void OnImageChanged(EventArgs e)
        {
            EventHandler handler = Events[EventImageChanged] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected virtual void OnFrameIndexChanged(GifBoxFrameIndexChangedEventArgs e)
        {
            FrameIndexChangedEventHandler handler = Events[EventFrameIndexChanged] as FrameIndexChangedEventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>   
        /// 开始循环播放动态图片   
        /// </summary>   
        private void StartAnimation()
        {
            lock (this.Image)
            {
                ImageAnimator.Animate(this.Image, new EventHandler(this.Image_FrameChanged));
                this.isruning = true;
            }
        }

        /// <summary>   
        /// 停止循环播放动态图片  
        /// </summary>   
        private void StopAnimation()
        {
            lock (this.Image)
            {
                ImageAnimator.StopAnimate(this.Image, new EventHandler(this.Image_FrameChanged));
                this.isruning = false;
            }
        }

        /// <summary>
        /// 当前帧更改事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Image_FrameChanged(object sender, EventArgs e)
        {
            if (!this.Visible)
            {
                this.StopAnimation();
                return;
            }

            this.currentFrame = this.currentFrame + 1 >= this.frameCount ? 0 : this.currentFrame + 1;
            lock (this.image)
            {
                this.image.SelectActiveFrame(this.frameDimension, this.currentFrame);
                this.Invalidate();

            }
            if (!this.DesignMode)
            {
                this.OnFrameIndexChanged(new GifBoxFrameIndexChangedEventArgs(this.currentFrame));
            }
        }

        /// <summary>
        /// 重置图片信息
        /// </summary>
        private void ResetImagetFrameInfo()
        {
            this.frameDimension = null;
            this.isAnimation = false;
            this.frameCount = 0;
            this.currentFrame = -1;
        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBorderColor = Color.Empty;
            private readonly Color defaultBorderColor = SystemColors.ActiveCaption;
            private Color borderColor = Color.Empty;
            /// <summary>
            /// 边框颜色
            /// </summary>
            [Description("边框颜色")]
            [PropertyOrder(-198)]
            [SkinProperty(true, false)]
            public Color BorderColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinBorderColor;
                    }

                    if (this.borderColor != Color.Empty)
                    {
                        return this.borderColor;
                    }

                    return this.defaultBorderColor;
                }
                set
                {
                    if (this.borderColor == value)
                        return;

                    this.borderColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBorderColor()
            {
                return this.borderColor != Color.Empty;
            }
            private void ResetBorderColor()
            {
                this.borderColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Control;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-195)]
            [SkinProperty(true, true)]
            public Color BackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinBackColor != Color.Empty)
                    {
                        return this.skinBackColor;
                    }

                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.BackColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinTextColor = Color.Empty;
            private readonly Color defaultTextColor = SystemColors.ControlText;
            private Color textColor = Color.Empty;
            /// <summary>
            /// 文本颜色
            /// </summary>
            [Description("文本颜色")]
            [PropertyOrder(-193)]
            [SkinProperty(true, true)]
            public Color TextColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinTextColor != Color.Empty)
                    {
                        return this.skinTextColor;
                    }

                    if (this.textColor != Color.Empty)
                    {
                        return this.textColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.ForeColor;
                    }

                    return this.defaultTextColor;
                }
                set
                {
                    if (this.textColor == value)
                        return;

                    this.textColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return this.textColor != Color.Empty;
            }
            private void ResetTextColor()
            {
                this.textColor = Color.Empty;
                this.Invalidate();
            }

            #endregion

        }

        #endregion

    }

}
